package com.tianquan.miracle.context;

import com.tianquan.miracle.annotation.Configuration;
import com.tianquan.miracle.annotation.Import;
import com.tianquan.miracle.aop.*;
import com.tianquan.miracle.aop.annotation.*;
import com.tianquan.miracle.beans.BeanDefinition;
import com.tianquan.miracle.beans.DefaultBeanFactory;
import com.tianquan.miracle.conditional.ParseConditionPostProcessor;
import com.tianquan.miracle.core.EnableAutoConfiguration;
import com.tianquan.miracle.listener.core.EventListener;
import com.tianquan.miracle.listener.core.EventSourceManager;
import com.tianquan.miracle.listener.print.PrintEvent;
import com.tianquan.miracle.postprocessor.BeanPostProcessor;
import com.tianquan.miracle.postprocessor.InjectBeanPostProcessor;
import com.tianquan.miracle.util.MiracleUtils;
import com.tianquan.miracle.util.ServiceClassLoader;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

/**
 * @BelongsProject: uploaddemo
 * @BelongsPackage: com.tianquan.miracle.context
 * @Author: tianquan
 * @CreateTime: 2024-09-30  11:16
 * @Description: 抽象应用上下文类，实现了应用上下文接口 提供了一些默认的实现，以及应用上下文初始化和Bean处理的基础设施
 * @Version: 1.0
 */
public abstract class AbstractApplicationContext implements ApplicationContext {

    /**
     * 在Bean后处理器处理Bean之前执行的一些预处理操作
     *
     * @param defaultBeanFactory 默认的Bean工厂，用于注册和管理Bean
     */
    protected void preBeanPostProcessor(DefaultBeanFactory defaultBeanFactory) {
        // 初始化框架需要的Bean
        initializingNecessaryBean(defaultBeanFactory);
        // 将自动配置类加入到容器中
        loadAutoConfiguration(defaultBeanFactory);
        // 拓展类,只需要了给全类名就可以在创建用户Bean前自定义Bean实现
        Set<String> classNameSet = extendPreBeanPostProcessor();
        // 注入到容器中
        for (String className : classNameSet) {
            try {
                Class<?> clazz = Class.forName(className);
                String beanName = MiracleUtils.createBeanName(clazz);
                BeanDefinition beanDefinition = new BeanDefinition(beanName, clazz, "singleton");
                defaultBeanFactory.registerBeanDefinition(beanName, beanDefinition);
                defaultBeanFactory.getBean(beanName);
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 解析并创建切面Bean
     *
     * @param defaultBeanFactory 默认的Bean工厂，用于注册和管理Bean
     */
    protected void parseCreateAspectBean(DefaultBeanFactory defaultBeanFactory) {
        List<BeanDefinition> allBeanDefinition = defaultBeanFactory.getAllBeanDefinition();
        for (BeanDefinition beanDefinition : allBeanDefinition) {
            Class<?> aClass = beanDefinition.getaClass();
            Aspect annotation = aClass.getAnnotation(Aspect.class);
            if (annotation == null) {
                continue;
            }
            Method[] methods = aClass.getDeclaredMethods();
            // 创建切面类
            AopEntity aopEntity = new AopEntity();
            // 设置切面类
            aopEntity.setObject(MiracleUtils.getBean(aClass));
            Pointcut pointcut = null;
            Method poinctcutMethod = null;
            for (Method method : methods) {
                // 设置切点
                Pointcut var1 = method.getAnnotation(Pointcut.class);
                if (var1 != null && pointcut == null) {
                    pointcut = var1;
                    poinctcutMethod = method;
                }
                // 设置前置通知
                if (MiracleUtils.parseMethod(method, Before.class) != null && aopEntity.getBeforeMethod() == null) {
                    aopEntity.setBeforeMethod(method);
                }
                // 设置环绕通知
                if (MiracleUtils.parseMethod(method, Around.class) != null && aopEntity.getAroundMethod() == null) {
                    aopEntity.setAroundMethod(method);
                }
                // 设置后置通知
                if (MiracleUtils.parseMethod(method, After.class) != null && aopEntity.getAfterMethod() == null) {
                    aopEntity.setAfterMethod(method);
                }
            }
            // 当前方法没有切点直接解析下一个bean定义对象
            if (pointcut == null) {
                continue;
            }
            // 判断切点方法是否为空
            if (aopEntity.getBeforeMethod() == null && aopEntity.getAfterMethod() == null && aopEntity.getAroundMethod() == null) {
                continue;
            }
            // 判断切点方法和通知上面的方法是否一致
            MiracleUtils.cheekAnnotation(aopEntity, poinctcutMethod.getName());
            // 设置需要代理的方法
            String[] methodList = pointcut.method();
            if (methodList != null && methodList.length > 0) {
                Arrays.stream(methodList).forEach(method -> defaultBeanFactory.putAopMethodsName(method, aopEntity));
            }
            // 设置需要代理的类
            Class<?>[] classes = pointcut.classArray();
            if (classes != null && classes.length > 0) {
                Arrays.stream(classes).forEach(classProxy -> defaultBeanFactory.putAopClass(classProxy, aopEntity));
            }
            // 设置需要代理的注解
            Class<? extends Annotation>[] annotations = pointcut.annotation();
            if (annotations != null && annotations.length > 0) {
                Arrays.stream(annotations).forEach(a -> defaultBeanFactory.putAopAnnotationName(a, aopEntity));
            }
        }
    }

    /**
     * 在Bean定义注册之后执行的一些处理操作
     *
     * @param defaultBeanFactory 默认的Bean工厂，用于注册和管理Bean
     */
    protected void postProcessorBeanDefinitionRegistry(DefaultBeanFactory defaultBeanFactory) {
        List<BeanDefinition> allBeanDefinition = defaultBeanFactory.getAllBeanDefinition();
        for (BeanDefinition beanDefinition : allBeanDefinition) {
            Class<?> aClass = beanDefinition.getaClass();
            // 判断该class有没有实现BeanPostProcessor接口
            if (BeanPostProcessor.class.isAssignableFrom(aClass)) {
                // 先实例化该类 将该类放入BeanPostProcessor容器里
                BeanPostProcessor beanPostProcessor = (BeanPostProcessor) defaultBeanFactory.getBean(aClass);
                defaultBeanFactory.addBeanPostProcessor(beanPostProcessor);
            }
        }
    }

    /**
     * 初始化必要的Bean
     *
     * @param defaultBeanFactory 默认的Bean工厂，用于注册和管理Bean
     */
    private void initializingNecessaryBean(DefaultBeanFactory defaultBeanFactory) {
        // 加载依赖注入需要的处理器
        List<InjectBeanPostProcessor> injectBeanPostProcessor = ServiceClassLoader.loaderService(InjectBeanPostProcessor.class);
        defaultBeanFactory.addInjectBeanPostProcessors(injectBeanPostProcessor);
        // 加载条件解析需要的处理器
        List<ParseConditionPostProcessor> parseConditionPostProcessors = ServiceClassLoader.loaderService(ParseConditionPostProcessor.class);
        defaultBeanFactory.addParseConditionPostProcessors(parseConditionPostProcessors);
        // 加载BeanPostProcessor
        List<BeanPostProcessor> beanPostProcessors = ServiceClassLoader.loaderService(BeanPostProcessor.class);
        if (beanPostProcessors != null) {
            beanPostProcessors.forEach(defaultBeanFactory::addBeanPostProcessor);
        }
    }

    /**
     * 加载自动配置的Bean
     *
     * @param defaultBeanFactory 默认的Bean工厂，用于注册和管理Bean
     */
    private void loadAutoConfiguration(DefaultBeanFactory defaultBeanFactory) {
        // 是否开启自动配置类
        if (!isEnabled()) {
            return;
        }
        // 拿到所有能自动配置的类
        Set<String> classNameSet = ServiceClassLoader.getClassName(EnableAutoConfiguration.class);
        excludeNoAutoConfiguration(classNameSet);
        if (classNameSet == null) {
            return;
        }
        for (String className : classNameSet) {
            try {
                Class<?> aClass = Class.forName(className);
                Configuration configuration = aClass.getAnnotation(Configuration.class);
                if (configuration != null) {
                    String beanName = MiracleUtils.createBeanName(aClass);
                    BeanDefinition beanDefinition = new BeanDefinition(beanName, aClass, "singleton");
                    defaultBeanFactory.registerBeanDefinition(beanName, beanDefinition);
                }
            } catch (ClassNotFoundException ignored) {
                System.out.println();
            } finally {
                // 添加到容器中
                defaultBeanFactory.loadBean();
            }
        }
    }

    /**
     * 排除不需要自动配置的类
     *
     * @param classNameSet 所有自动配置类的名称集合
     */
    private void excludeNoAutoConfiguration(Set<String> classNameSet) {
        //  排除掉用户不需要自动配置的类
    }

    /**
     * 初始化Bean定义
     *
     * @param defaultBeanFactory 默认的Bean工厂，用于注册和管理Bean
     */
    public void initBeanDefinition(DefaultBeanFactory defaultBeanFactory) {
        // 扫描要添加的bean
        List<Class<?>> classesInPackageAndSubpackages = findClassesInPackageAndSubpackages();
        for (Class<?> clazz : classesInPackageAndSubpackages) {
            // 判断是否是需要自动生成的Bean
            String beanName = MiracleUtils.sanComponentAndCreateBeanName(clazz);
            if (beanName == null) {
                continue;
            }
            // 需要生成Bean定义对象
            BeanDefinition beanDefinition = new BeanDefinition(beanName, clazz, "singleton");
            // 向容器中添加Bean定义对象
            defaultBeanFactory.registerBeanDefinition(beanName, beanDefinition);
            // 判断class上是否有@Import注解
            parseImport(defaultBeanFactory, clazz);
        }
    }

    /**
     * 解析Import注解
     *
     * @param defaultBeanFactory 默认的Bean工厂，用于注册和管理Bean
     * @param clazz              当前处理的类
     */
    private void parseImport(DefaultBeanFactory defaultBeanFactory, Class<?> clazz) {
        Import annotation = clazz.getAnnotation(Import.class);
        if (annotation == null) {
            return;
        }
        Class<?>[] classes = annotation.value();
        for (Class<?> aClass : classes) {
            String beanName = MiracleUtils.createBeanName(aClass);
            BeanDefinition beanDefinition = new BeanDefinition(beanName, aClass, "singleton");
            defaultBeanFactory.registerBeanDefinition(beanName, beanDefinition);
        }
    }

    /**
     * 初始化Beans
     *
     * @param defaultBeanFactory 默认的Bean工厂，用于注册和管理Bean
     */
    void initializingBeans(DefaultBeanFactory defaultBeanFactory) {
        defaultBeanFactory.loadBean();
    }

    /**
     * 在Bean后处理器处理Bean之后执行的一些操作
     *
     * @param defaultBeanFactory 默认的Bean工厂，用于注册和管理Bean
     * @param eventSourceManager 事件源管理器，用于管理事件监听器
     */
    public void postBeanPostProcessor(DefaultBeanFactory defaultBeanFactory, EventSourceManager eventSourceManager) {
        // 将实现了EventListener接口的类注册到监听器管理者里面
        List<EventListener> listeners = defaultBeanFactory.selectBean(EventListener.class);
        eventSourceManager.addEventListeners(listeners);
        // 发布打印事件
        eventSourceManager.publishEvent(new PrintEvent(null));
    }

    /**
     * 判断是否启用自动配置
     *
     * @return 如果启用自动配置返回true，否则返回false
     */
    abstract Boolean isEnabled();

    /**
     * 找到并返回指定包及其子包中的所有类
     *
     * @return 包含所有类的列表
     */
    public abstract List<Class<?>> findClassesInPackageAndSubpackages();

    /**
     * 返回需要在创建用户Bean之前处理的Bean类名集合
     *
     * @return Bean类名集合
     */
    public abstract Set<String> extendPreBeanPostProcessor();
}

